﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using Lswweb.IDAL;
using Lswweb.Model;
using Ue.Framework.Collections;

namespace Lswweb.SqlServerDAL
{
    /// <summary>
    /// 会员资格类
    /// </summary>
    public class UsersDAL : IUsers
    {
        private Builder<UserInfo> memberBuilder = new Builder<UserInfo>("Users","Id");
        private UserProfileDAL profileDAL = UserProfileDAL.ProfileDAL;

        public UsersDAL()
        {
            memberBuilder.CreateModel += new ReaderBind<UserInfo>(ReaderBind);
            memberBuilder.GetParameters += new ParametersBuilder<UserInfo>(GetParameters);
        }

        public UserInfo GetUser(int userId)
        {
            return GetUser(userId,string.Empty);
        }
        public UserInfo GetUser(string loginName)
        {
            return GetUser(0,loginName);
        }
        private UserInfo GetUser(int userId, string loginName)
        {
            if (userId <= 0 && string.IsNullOrEmpty(loginName))
                return null;

            string where = "Id=@Id or LoginName=@LoginName";
            string orderBy = "id desc";
            IDataParameter[] parameters = { new SqlParameter("@Id",userId),
                                            new SqlParameter("@LoginName",loginName)};

            UserInfo userInfo = memberBuilder.GetModel(string.Empty, string.Empty, where, orderBy, parameters);
            if (userInfo != null)
            {
                userInfo.IsAdmin = UserAdminDAL.AdminDAL.IsAdmin(userInfo.Id);
                userInfo.Profile = this.profileDAL.GetProfile(userInfo.Id);
            }

            return userInfo;
        }

        public IList<UserInfo> GetUsers(string searchKey, StatusType statusType, RoleType roleType, int pageSize, int pageIndex, out int record)
        {
            string tableName = "Users";
            StringBuilder where = new StringBuilder();
            IList<IDataParameter> list = new List<IDataParameter>();

            //SearchKey搜索条件
            if (!string.IsNullOrEmpty(searchKey))
            {
                list.Add(DataAccess.CreateParameter("@SearchKey", searchKey));
                where.Append(" and LoginName like '%'+ @SearchKey + '%'");
            }

            //statusType条件
            if (Enum.IsDefined(typeof(StatusType), statusType))
            {
                list.Add(DataAccess.CreateParameter("@Status", (int)statusType));
                where.Append(" and Status=@Status");
            }

            //roleType条件
            if (Enum.IsDefined(typeof(RoleType), roleType))
            {
                switch (roleType)
                {
                    case RoleType.Admin:
                        tableName += ",AdminUsers";
                        where.Append(" and AdminUsers.UserId=Users.Id");
                        break;
                    case RoleType.Member:
                    default:
                        where.Append(" and not exists(select UserId from AdminUsers where UserId=Users.Id)");
                        break;
                }
            }

            IDataParameter[] parameters = new IDataParameter[list.Count];
            list.CopyTo(parameters, 0);
            return memberBuilder.GetModels(tableName,string.Empty,string.Empty,where.ToString().Remove(0, 5),"Id desc",pageIndex, pageSize, out record, parameters);
        }


        /// <summary>
        /// 添加用户资格，返回新添加用户资格的Id
        /// </summary>
        /// <param name="userInfo">用户实体类</param>
        /// <returns>成功返回用户Id，添加失败则返回0</returns>
        public int Insert(UserInfo userInfo)
        {
            if (userInfo.DateCreated == DateTime.MaxValue || userInfo.DateCreated == DateTime.MinValue)
                userInfo.DateCreated = DateTime.Now;

            int result = memberBuilder.Insert(
                userInfo,
                "LoginName",
                "Password",
                "PasswordQuestion",
                "PasswordAnswer",
                "Email",
                "Status",
                "DateCreated",
                "Describes");

            if (result > 0 && userInfo.Profile != null)
            {
                userInfo.Profile.UserId = result;
                result = this.profileDAL.Insert(userInfo.Profile);
                if (result <= 0)
                    this.Delete(userInfo.Profile.UserId);
            }

            return result;
        }


        /// <summary>
        /// 更新用户资格，未更新DateCreated和LastLoginDate字段
        /// </summary>
        /// <param name="userInfo">用户资格信息</param>
        /// <returns>更新成功反回true,失败返回false</returns>
        public bool Update(UserInfo userInfo)
        {
            string update = "update Users set LoginName=@LoginName,Password=@Password,PasswordQuestion=@PasswordQuestion,PasswordAnswer=@PasswordAnswer,Email=@Email,Status=@Status,Describes=@Describes where Id=@Id;";
            bool result = memberBuilder.Update(update, userInfo);
            if (result)
                result = this.profileDAL.Update(userInfo.Profile);
            
            return result;
        }
        

        /// <summary>
        /// 根据用户Id或用户登录名更新用户密码
        /// </summary>
        /// <param name="userId">用户Id</param>
        /// <param name="newPsw">新密码</param>
        /// <returns>更新成功反回true,失败返回false</returns>
        public bool UpdatePsw(int userId, string newPsw)
        {
            if (string.IsNullOrEmpty(newPsw))
                return false;

            IDataParameter[] parameters = new IDataParameter[3];
            parameters[0] = new SqlParameter("@Id", userId);
            parameters[1] = new SqlParameter("@Password", newPsw);

            string where = "Id=@Id";

            return memberBuilder.UpdateFields("Password", where, parameters);
        }

        /// <summary>
        /// 根据用户Id更新用户状态
        /// </summary>
        /// <param name="userId">用户Id</param>
        /// <param name="statusType">用户状态</param>
        /// <returns>更新成功反回true,失败返回false</returns>
        public bool UpdateStatus(int userId,StatusType statusType)
        {
            if (userId <= 0 || !Enum.IsDefined(typeof(StatusType), statusType))
                return false;

            IDataParameter[] parameters = new IDataParameter[3];
            parameters[0] = new SqlParameter("@Id", userId);
            parameters[1] = new SqlParameter("@Status", (int)statusType);

            string where = "Id=@Id";

            return memberBuilder.UpdateFields("Status", where, parameters);
        }

        /// <summary>
        /// 删除用户资格
        /// </summary>
        /// <param name="userId">用户Id</param>
        /// <returns>删除成功反回true,失败返回false</returns>
        public bool Delete(int userId)
        {
            if (userId <= 0)
                return false;

            return memberBuilder.Delete(userId);
        }

        public bool IsHas(int userId, string loginName)
        {
            return memberBuilder.IsHas(userId, "LoginName", loginName);
        }

        #region Profile

        public UserProfileInfo GetProfile(int userId)
        {
            return this.profileDAL.GetProfile(userId);
        }

        public bool UpdateProfile(UserProfileInfo profileInfo)
        {
            if(this.profileDAL.IsHas(profileInfo.UserId))
                return this.profileDAL.Update(profileInfo);
            else
                return this.profileDAL.Insert(profileInfo)==profileInfo.UserId;
        }

        #endregion

        #region Admin Power

        public string GetAdminPowers(int id)
        {
            return UserAdminDAL.AdminDAL.GetPowerStr(id);
        }

        public bool UpdateAdminPowers(int id, string powerStr)
        {
            return UserAdminDAL.AdminDAL.Update(id, powerStr);
        }

        public bool UpdateIsAdmin(string userName, bool isAdmin)
        {
            UserInfo userInfo = GetUser(0, userName);
            if (userInfo == null)
                return false;

            if (isAdmin)
                return Convert.ToBoolean(UserAdminDAL.AdminDAL.Insert(userInfo.Id, string.Empty));
            else
                return Convert.ToBoolean(UserAdminDAL.AdminDAL.Delete(userInfo.Id));
        }

        #endregion

        #region Protected Methods

        /// <summary>
        /// 根据实体类生成sql参数
        /// </summary>
        /// <param name="userInfo">实体类</param>
        /// <returns>参数集合</returns>
        protected IDataParameter[] GetParameters(UserInfo userInfo)
        {
            if (userInfo == null)
                return new IDataParameter[0];

             return new IDataParameter[]{   
                DataAccess.CreateParameter("@Id",userInfo.Id),
                DataAccess.CreateParameter("@LoginName",userInfo.LoginName), 
                DataAccess.CreateParameter("@Password",userInfo.Password), 
                DataAccess.CreateParameter("@PasswordQuestion",userInfo.PasswordQuestion), 
                DataAccess.CreateParameter("@PasswordAnswer",userInfo.PasswordAnswer), 
                DataAccess.CreateParameter("@Email",userInfo.Email), 
                DataAccess.CreateParameter("@Status",(int)userInfo.Status),
                DataAccess.CreateParameter("@DateCreated",userInfo.DateCreated),
                DataAccess.CreateParameter("@Describes",userInfo.Describes)};
        }

        /// <summary>
        /// 根据DataReader生成实体类
        /// </summary>
        /// <param name="dataReader"></param>
        /// <returns></returns>
        protected UserInfo ReaderBind(Hashtable dataReader)
        {
            return new UserInfo()
            {
                Id = dataReader.Get<int>("Id"),
                LoginName = dataReader.Get<string>("LoginName"),
                Password = dataReader.Get<string>("Password"),
                Email = dataReader.Get<string>("Email"),
                PasswordAnswer = dataReader.Get<string>("PasswordAnswer"),
                PasswordQuestion = dataReader.Get<QuestionType>("PasswordQuestion"),
                DateCreated = dataReader.Get<DateTime>("DateCreated"),
                LastLoginDate = dataReader.Get<DateTime>("LastLoginDate"),
                Status = dataReader.Get<StatusType>("Status"),
                Describes = dataReader.Get<string>("Describes")
            };

        }

        #endregion
    }

    /// <summary>
    ///  会员资料信息类
    /// </summary>
    internal class UserProfileDAL
    {
        private Builder<UserProfileInfo> profileBuilder = new Builder<UserProfileInfo>("UserProfile", "UserId");

        private UserProfileDAL()
        {
            profileBuilder.CreateModel += new ReaderBind<UserProfileInfo>(ReaderBind);
            profileBuilder.GetParameters += new ParametersBuilder<UserProfileInfo>(GetParameters);
        }

        #region 获取 UserProfileDAL

        private static UserProfileDAL profileDAL;
        public static UserProfileDAL ProfileDAL
        {
            get
            {
                if (profileDAL == null)
                    profileDAL = new UserProfileDAL();
                return profileDAL;
            }
        }

        #endregion

        public UserProfileInfo GetProfile(int userId)
        {
            return profileBuilder.GetModel(userId);
        }

        public int Insert(UserProfileInfo profileInfo)
        {
            if (profileInfo.UserId <= 0)
                return 0;

            try
            {
                this.profileBuilder.Insert(
                    profileInfo,
                    "UserId",
                    "CompanyName",
                    "Name",
                    "Sex",
                    "Mobile",
                    "Phone",
                    "Fax",
                    "CityId",
                    "Street",
                    "PostCode");

                return profileInfo.UserId;
            }
            catch
            {
                return 0;
            }
        }

        public bool Update(UserProfileInfo profileInfo)
        {
            return this.profileBuilder.Update(
                profileInfo,
                "UserId=@UserId",
                "Name",
                "Sex",
                "Mobile",
                "Phone",
                "Fax",
                "CityId",
                "Street",
                "PostCode",
                "CompanyName");
        }

        public bool IsHas(int userId)
        {
            return profileBuilder.IsHas(userId);
        }

        #region Protected Methods

        protected IDataParameter[] GetParameters(UserProfileInfo profileInfo)
        {
            if (profileInfo == null)
                return new IDataParameter[0];

            return new IDataParameter[] {
                DataAccess.CreateParameter("@UserId", profileInfo.UserId),
                DataAccess.CreateParameter("@Name", profileInfo.Name),
                DataAccess.CreateParameter("@Sex", profileInfo.Sex),
                DataAccess.CreateParameter("@Mobile", profileInfo.Mobile),
                DataAccess.CreateParameter("@Phone", profileInfo.Phone),
                DataAccess.CreateParameter("@Fax", profileInfo.Fax),
                DataAccess.CreateParameter("@CityId", profileInfo.CityId),
                DataAccess.CreateParameter("@Street", profileInfo.Street),
                DataAccess.CreateParameter("@PostCode", profileInfo.PostCode),
                DataAccess.CreateParameter("@CompanyName",profileInfo.CompanyName)};
        }

        protected UserProfileInfo ReaderBind(Hashtable dataReader)
        {
            return new UserProfileInfo()
            {
                UserId = dataReader.Get<int>("UserId"),
                Name = dataReader.Get<string>("Name"),
                Sex = dataReader.Get<SexType>("Sex"),
                Mobile = dataReader.Get<string>("Mobile"),
                Phone = dataReader.Get<string>("Phone"),
                Fax = dataReader.Get<string>("Fax"),
                CityId = dataReader.Get<int>("CityId"),
                Street = dataReader.Get<string>("Street"),
                PostCode = dataReader.Get<string>("PostCode"),
                CompanyName = dataReader.Get<string>("CompanyName")
            };
        }

        #endregion
    }

    /// <summary>
    /// 管理员信息类
    /// </summary>
    internal class UserAdminDAL
    {
        private UserAdminDAL() { }

        private static UserAdminDAL adminDAL;
        public static UserAdminDAL AdminDAL
        {
            get
            {
                if (adminDAL == null)
                    adminDAL = new UserAdminDAL();
                return adminDAL;
            }
        }

        public int Insert(int userId, string powerStr)
        {
            if (userId <= 0)
                return 0;

            if (IsAdmin(userId))
                return userId;

            StringBuilder strSql = new StringBuilder();
            strSql.Append("insert into AdminUsers(");
            strSql.Append("UserId,Powers)");

            strSql.Append(" values (");
            strSql.Append("@UserId,@Powers);");
            strSql.Append("select @@Identity;");

            bool label = Convert.ToBoolean(DataAccess.ExecuteNonQuery(strSql.ToString(), GetParameters(userId, powerStr)));
            return label ? userId : 0;
        }

        public bool Delete(int userId)
        {
            string sql = "delete AdminUsers where UserId=@UserId;";
            IDataParameter parameter = DataAccess.CreateParameter("@UserId", userId);
            return Convert.ToBoolean(DataAccess.ExecuteNonQuery(sql, parameter));
        }

        public bool Update(int userId, string powerStr)
        {
            StringBuilder strSql = new StringBuilder();
            strSql.Append("update AdminUsers set ");
            strSql.Append("Powers=@Powers");
            strSql.Append(" where UserId=@UserId ");

            return Convert.ToBoolean(DataAccess.ExecuteNonQuery(strSql.ToString(), GetParameters(userId, powerStr)));
        }

        public string GetPowerStr(int userId)
        {
            if (userId <= 0)
                return string.Empty;

            string sql = "select Powers from AdminUsers where UserId=@UserId;";
            return DataAccess.ExecuteScalar(sql, new SqlParameter("@UserId", userId)).ToString();
        }

        public bool IsAdmin(int userId)
        {
            if (userId <= 0)
                return false;

            string where = "UserId=@UserId";
            IDataParameter parameter = DataAccess.CreateParameter("@UserId", userId);
            return Convert.ToBoolean(DataAccess.GetRecord("AdminUsers", where, parameter));
        }

        private IDataParameter[] GetParameters(int userId, string powerStr)
        {
            IDataParameter[] parameters ={  new SqlParameter("@UserId",userId),
                                            new SqlParameter("@Powers",powerStr)};
            return parameters;
        }
    }

}